home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -screenplay- / shareware / warpquake / warpquakesrc / net_amigaudp.c < prev    next >
C/C++ Source or Header  |  2000-02-29  |  12KB  |  464 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // net_udp.c
  21.  
  22. #include "quakedef.h"
  23.  
  24. #include <exec/exec.h>
  25. #include <powerup/ppcproto/exec.h>
  26.  
  27. #include <sys/types.h>
  28. #include <sys/socket.h>
  29. #include <netinet/in.h>
  30. #include <netdb.h>
  31. #include <sys/param.h>
  32. #include <sys/ioctl.h>
  33. #include <errno.h>
  34.  
  35. #include <powerup/ppcproto/exec.h>
  36. #include <powerup/ppcproto/socket.h>
  37.  
  38. /*#ifdef __PPC__
  39. #ifdef __STORM__
  40. #include <clib/exec_protos.h>
  41. #else
  42. #include <proto/exec.h>
  43. #endif
  44. #include <clib/socket_protos.h>
  45. #else
  46. #include <proto/exec.h>
  47. #include <proto/socket.h>
  48. #endif*/
  49.  
  50.  
  51.  
  52. extern void I_Error (char *error, ...);
  53. extern cvar_t hostname;
  54.  
  55. struct Library *SocketBase = NULL;
  56.  
  57. static int net_acceptsocket = -1;        // socket for fielding new connections
  58. static int net_controlsocket = -1;
  59. static int net_broadcastsocket = 0;
  60. static struct qsockaddr broadcastaddr;
  61.  
  62. static unsigned long myAddr;
  63.  
  64. #include "net_udp.h"
  65.  
  66. //=============================================================================
  67.  
  68. int UDP_Init (void)
  69. {
  70.     struct hostent *local;
  71.     char    buff[MAXHOSTNAMELEN];
  72.     struct qsockaddr addr;
  73.     char *colon;
  74.     
  75. //    Con_Printf ("UDP_Init()\n");
  76.     if (COM_CheckParm ("-noudp"))
  77.         return -1;
  78.  
  79.         if ((SocketBase = OpenLibrary ("bsdsocket.library", 0)) == NULL) {
  80.           Con_Printf ("OpenLibrary(\"bsdsocket.library\") failed, no networking available\n");
  81.           return -1;
  82.         }
  83.  
  84.     // determine my name & address
  85.     gethostname(buff, MAXHOSTNAMELEN);
  86.     local = gethostbyname(buff);
  87.     myAddr = *(int *)local->h_addr_list[0];
  88.  
  89.     // if the quake hostname isn't set, set it to the machine name
  90.     if (Q_strcmp(hostname.string, "UNNAMED") == 0)
  91.     {
  92.         buff[15] = 0;
  93.         Cvar_Set ("hostname", buff);
  94.     }
  95.  
  96.     if ((net_controlsocket = UDP_OpenSocket (0)) == -1)
  97.         Sys_Error("UDP_Init: Unable to open control socket\n");
  98.  
  99.     ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
  100.     ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
  101.     ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport);
  102.  
  103.     UDP_GetSocketAddr (net_controlsocket, &addr);
  104.     Q_strcpy(my_tcpip_address,  UDP_AddrToString (&addr));
  105.     colon = Q_strrchr (my_tcpip_address, ':');
  106.     if (colon)
  107.         *colon = 0;
  108.  
  109.     Con_Printf("UDP Initialized\n");
  110.     tcpipAvailable = true;
  111.  
  112.     return net_controlsocket;
  113. }
  114.  
  115. //=============================================================================
  116.  
  117. void UDP_Shutdown (void)
  118. {
  119. //    Con_Printf ("UDP_Shutdown()\n");
  120.     if (SocketBase != NULL) {
  121.         UDP_Listen (false);
  122.         if (net_controlsocket != -1) {
  123.             UDP_CloseSocket (net_controlsocket);
  124.             net_controlsocket = -1;
  125.         }
  126.         CloseLibrary (SocketBase);
  127.         SocketBase = NULL;
  128.     }
  129. }
  130.  
  131. //=============================================================================
  132.  
  133. void UDP_Listen (qboolean state)
  134. {
  135. //    Con_Printf ("UDP_Listen()\n");
  136.     // enable listening
  137.     if (state)
  138.     {
  139.         if (net_acceptsocket != -1)
  140.             return;
  141.         if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1)
  142.             Sys_Error ("UDP_Listen: Unable to open accept socket\n");
  143.         return;
  144.     }
  145.  
  146.     // disable listening
  147.     if (net_acceptsocket == -1)
  148.         return;
  149.     UDP_CloseSocket (net_acceptsocket);
  150.     net_acceptsocket = -1;
  151. }
  152.  
  153. //=============================================================================
  154.  
  155. int UDP_OpenSocket (int port)
  156. {
  157.     int newsocket;
  158.     struct sockaddr_in address;
  159.     long _true = true;
  160.  
  161. //    Con_Printf ("UDP_OpenSocket()\n");
  162.     if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  163.         return -1;
  164.  
  165.     if (IoctlSocket (newsocket, FIONBIO, (char *)&_true) == -1)
  166.         goto ErrorReturn;
  167.  
  168.     address.sin_family = AF_INET;
  169.     address.sin_addr.s_addr = INADDR_ANY;
  170.     address.sin_port = htons(port);
  171.     if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
  172.         goto ErrorReturn;
  173.  
  174.     return newsocket;
  175.  
  176. ErrorReturn:
  177.     CloseSocket (newsocket);
  178.     return -1;
  179. }
  180.  
  181. //=============================================================================
  182.  
  183. int UDP_CloseSocket (int socket)
  184. {
  185. //    Con_Printf ("UDP_CloseSocket()\n");
  186.     if (socket == net_broadcastsocket)
  187.         net_broadcastsocket = 0;
  188.     return CloseSocket (socket);
  189. }
  190.  
  191.  
  192. //=============================================================================
  193. /*
  194. ============
  195. PartialIPAddress
  196.  
  197. this lets you type only as much of the net address as required, using
  198. the local network components to fill in the rest
  199. ============
  200. */
  201. static int PartialIPAddress (char *in, struct qsockaddr *hostaddr)
  202. {
  203.     char buff[256];
  204.     char *b;
  205.     int addr;
  206.     int num;
  207.     int mask;
  208.     int run;
  209.     int port;
  210.     
  211. //    Con_Printf ("UDP_PartialIPAddress()\n");
  212.     buff[0] = '.';
  213.     b = buff;
  214.     strcpy(buff+1, in);
  215.     if (buff[1] == '.')
  216.         b++;
  217.  
  218.     addr = 0;
  219.     mask=-1;
  220.     while (*b == '.')
  221.     {
  222.         b++;
  223.         num = 0;
  224.         run = 0;
  225.         while (!( *b < '0' || *b > '9'))
  226.         {
  227.           num = num*10 + *b++ - '0';
  228.           if (++run > 3)
  229.               return -1;
  230.         }
  231.         if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
  232.             return -1;
  233.         if (num < 0 || num > 255)
  234.             return -1;
  235.         mask<<=8;
  236.         addr = (addr<<8) + num;
  237.     }
  238.     
  239.     if (*b++ == ':')
  240.         port = Q_atoi(b);
  241.     else
  242.         port = net_hostport;
  243.  
  244.     ((struct sockaddr_in *)hostaddr)->sin_family = AF_INET;
  245.     ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);    
  246.     ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
  247.     
  248.     return 0;
  249. }
  250. //=============================================================================
  251.  
  252. int UDP_Connect (int socket, struct qsockaddr *addr)
  253. {
  254. //    Con_Printf ("UDP_Connect()\n");
  255.     return 0;
  256. }
  257.  
  258. //=============================================================================
  259.  
  260. int UDP_CheckNewConnections (void)
  261. {
  262.     long    available;
  263.  
  264. //    Con_Printf ("UDP_CheckNewConnections()\n");
  265.     if (net_acceptsocket == -1)
  266.         return -1;
  267.  
  268.     if (IoctlSocket (net_acceptsocket, FIONREAD, (char *)&available) == -1)
  269.         Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n");
  270.     if (available)
  271.         return net_acceptsocket;
  272.     return -1;
  273. }
  274.  
  275. //=============================================================================
  276.  
  277. int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
  278. {
  279.     LONG addrlen = sizeof (struct qsockaddr);
  280.     int ret;
  281.     long err;
  282.  
  283. //    Con_Printf ("UDP_Read()\n");
  284.     ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
  285.     err = Errno();
  286.     if (ret == -1 && (err == EWOULDBLOCK || err == ECONNREFUSED))
  287.         return 0;
  288.     return ret;
  289. }
  290.  
  291. //=============================================================================
  292.  
  293. int UDP_MakeSocketBroadcastCapable (int socket)
  294. {
  295.     int                i = 1;
  296.  
  297. //    Con_Printf ("UDP_MakeSocketBroadcastCapable()\n");
  298.     // make this socket broadcast capable
  299.     if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
  300.         return -1;
  301.     net_broadcastsocket = socket;
  302.  
  303.     return 0;
  304. }
  305.  
  306. //=============================================================================
  307.  
  308. int UDP_Broadcast (int socket, byte *buf, int len)
  309. {
  310.     int ret;
  311.  
  312. //    Con_Printf ("UDP_Broadcast()\n");
  313.     if (socket != net_broadcastsocket)
  314.     {
  315.         if (net_broadcastsocket != 0)
  316.             Sys_Error("Attempted to use multiple broadcasts sockets\n");
  317.         ret = UDP_MakeSocketBroadcastCapable (socket);
  318.         if (ret == -1)
  319.         {
  320.             Con_Printf("Unable to make socket broadcast capable\n");
  321.             return ret;
  322.         }
  323.     }
  324.  
  325.     return UDP_Write (socket, buf, len, &broadcastaddr);
  326. }
  327.  
  328. //=============================================================================
  329.  
  330. int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
  331. {
  332.     int ret;
  333.  
  334. //    Con_Printf ("UDP_Write()\n");
  335.     ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
  336.     if (ret == -1 && Errno() == EWOULDBLOCK)
  337.         return 0;
  338.     return ret;
  339. }
  340.  
  341. //=============================================================================
  342.  
  343. char *UDP_AddrToString (struct qsockaddr *addr)
  344. {
  345.     static char buffer[22];
  346.     int haddr;
  347.  
  348. //    Con_Printf ("UDP_AddrToString()\n");
  349.     haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
  350.     sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff,
  351.             (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff,
  352.             ntohs(((struct sockaddr_in *)addr)->sin_port));
  353.     return buffer;
  354. }
  355.  
  356. //=============================================================================
  357.  
  358. int UDP_StringToAddr (char *string, struct qsockaddr *addr)
  359. {
  360.     int ha1, ha2, ha3, ha4, hp;
  361.     int ipaddr;
  362.  
  363. //    Con_Printf ("UDP_StringToAddr()\n");
  364.     sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
  365.     ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
  366.  
  367.     ((struct sockaddr_in *)addr)->sin_family = AF_INET;
  368.     ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
  369.     ((struct sockaddr_in *)addr)->sin_port = htons(hp);
  370.     return 0;
  371. }
  372.  
  373. //=============================================================================
  374.  
  375. int UDP_GetSocketAddr (int socket, struct qsockaddr *addr)
  376. {
  377.     LONG addrlen = sizeof(struct qsockaddr);
  378.     unsigned int a;
  379.  
  380. //    Con_Printf ("UDP_GetSocketAddr()\n");
  381.     Q_memset(addr, 0, sizeof(struct qsockaddr));
  382.     getsockname(socket, (struct sockaddr *)addr, &addrlen);
  383.     a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
  384.     if (a == 0 || a == inet_addr("127.0.0.1"))
  385.         ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
  386.  
  387.     return 0;
  388. }
  389.  
  390. //=============================================================================
  391.  
  392. int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name)
  393. {
  394.     struct hostent *hostentry;
  395.  
  396. //    Con_Printf ("UDP_GetNameFromAddr()\n");
  397.     hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
  398.     if (hostentry)
  399.     {
  400.         Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
  401.         return 0;
  402.     }
  403.  
  404.     Q_strcpy (name, UDP_AddrToString (addr));
  405.     return 0;
  406. }
  407.  
  408. //=============================================================================
  409.  
  410. int UDP_GetAddrFromName(char *name, struct qsockaddr *addr)
  411. {
  412.     struct hostent *hostentry;
  413.  
  414. //    Con_Printf ("UDP_GetAddrFromName()\n");
  415.     if (name[0] >= '0' && name[0] <= '9')
  416.         return PartialIPAddress (name, addr);
  417.     
  418.     hostentry = gethostbyname (name);
  419.     if (!hostentry)
  420.         return -1;
  421.  
  422.     ((struct sockaddr_in *)addr)->sin_family = AF_INET;
  423.     ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);    
  424.     ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
  425.  
  426.     return 0;
  427. }
  428.  
  429. //=============================================================================
  430.  
  431. int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
  432. {
  433. //    Con_Printf ("UDP_AddrCompare()\n");
  434.  
  435.     if (((struct sockaddr_in *)addr1)->sin_family !=
  436.             ((struct sockaddr_in *)addr2)->sin_family)
  437.         return -1;
  438.  
  439.     if (((struct sockaddr_in *)addr1)->sin_addr.s_addr !=
  440.             ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
  441.         return -1;
  442.  
  443.     if (((struct sockaddr_in *)addr1)->sin_port !=
  444.             ((struct sockaddr_in *)addr2)->sin_port)
  445.         return 1;
  446.  
  447.     return 0;
  448. }
  449.  
  450. //=============================================================================
  451.  
  452. int UDP_GetSocketPort (struct qsockaddr *addr)
  453. {
  454. //    Con_Printf ("UDP_GetSocketPort()\n");
  455.     return ntohs(((struct sockaddr_in *)addr)->sin_port);
  456. }
  457.  
  458.  
  459. int UDP_SetSocketPort (struct qsockaddr *addr, int port)
  460. {
  461.     ((struct sockaddr_in *)addr)->sin_port = htons(port);
  462.     return 0;
  463. }
  464.